/**
 *
 * by littlefean
 */

let LEN = 350;  // 画布边长
let OPEN_GRID = false;  // 是否显示网格
let OPEN_NUMBER = false;  // 是否显示数字
let RANGE = 10;  // 范围
let GRID_LEN = 1;  // 网格间距
let GRID_GRAY = 20;  // 网格灰度颜色 0~255

/**
 * 画网格
 * @param ele canvas 元素
 * @param range 表示 -R到R的绘图范围
 */
function drawCoordinate(ele, range) {
    let ctx = ele.getContext('2d');
    // 先画背景
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, LEN, LEN);

    // 计算现在一个单位长度是多少像素
    let numberLen = LEN / 2 / RANGE;
    let stepLen = numberLen * GRID_LEN;


    if (OPEN_GRID) {
        // 开启网格模式
        ctx.beginPath();

        ctx.strokeStyle = `rgb(${GRID_GRAY}, ${GRID_GRAY}, ${GRID_GRAY})`;

        // 画竖线
        let px = LEN / 2;
        while (px < LEN) {
            px += stepLen;
            ctx.moveTo(px, 0);
            ctx.lineTo(px, LEN);
            ctx.stroke();
        }
        px = LEN / 2;
        while (px > 0) {
            px -= stepLen;
            ctx.moveTo(px, 0);
            ctx.lineTo(px, LEN);
            ctx.stroke();
        }
        ctx.closePath();
        ctx.beginPath();
        // 画横线
        let py = LEN / 2;
        while (py < LEN) {
            py += stepLen;
            ctx.moveTo(0, py);
            ctx.lineTo(LEN, py);
            ctx.stroke();
        }

        py = LEN / 2;
        while (py > 0) {
            py -= stepLen;
            ctx.moveTo(0, py);
            ctx.lineTo(LEN, py);
            ctx.stroke();
        }
        ctx.closePath();
    }
    if (OPEN_NUMBER) {
        // 开启数字显示
        ctx.font = "20px 黑体";
        ctx.fillStyle = "gray";
        ctx.textAlign = "left";
        ctx.textBaseline = "top";

        // 画x轴刻度
        let px = LEN / 2;
        let x = 0;
        while (px < LEN) {
            px += stepLen;
            x += GRID_LEN;
            ctx.fillText(x.toString(), px, LEN / 2, 50);
        }
        px = LEN / 2;
        x = 0;
        while (px > 0) {
            px -= stepLen;
            x -= GRID_LEN;
            ctx.fillText(x.toString(), px, LEN / 2, 50);
        }
        // 画y轴刻度
        let py = LEN / 2;
        let y = 0;
        while (py < LEN) {
            py += stepLen;
            y -= GRID_LEN;
            ctx.fillText(y.toString(), LEN / 2, py, 50);
        }

        py = LEN / 2;
        y = 0
        while (py > 0) {
            py -= stepLen;
            y += GRID_LEN;
            ctx.fillText(y.toString(), LEN / 2, py, 50);
        }
    }

    ctx.strokeStyle = "white";
    ctx.strokeWidth = 1;
    // 画x轴横线
    ctx.beginPath();
    ctx.moveTo(0, LEN / 2);
    ctx.lineTo(LEN, LEN / 2);
    ctx.stroke();
    // 画y轴竖线
    ctx.moveTo(LEN / 2, 0);
    ctx.lineTo(LEN / 2, LEN);
    ctx.stroke();
    ctx.closePath();
}

/**
 * 画一条线段
 * @param ctx
 * @param x1
 * @param y1
 * @param x2
 * @param y2
 * @param color
 * @param w
 */
function drawLine(ctx, x1, y1, x2, y2, color, w) {
    ctx.strokeStyle = color;
    ctx.strokeWidth = w;
    ctx.beginPath();
    ctx.moveTo(x1, y1);
    ctx.lineTo(x2, y2);
    ctx.stroke();
    ctx.closePath();
}


/**
 * 画一个函数
 * @param ele canvas标签
 * @param f 函数对象
 * @param range
 * @param color 函数的颜色
 */
function drawFunc(ele, f, range, color = "red") {
    let ctx = ele.getContext('2d');

    let pArr = [];
    for (let ipx = 0; ipx <= LEN; ipx++) {
        // 遍历每一个像素点x位置
        let x = range * (ipx - LEN / 2) / (LEN / 2);
        let y = f(x);
        let ipy = y * ((LEN / 2) / range);
        ipy = LEN / 2 - ipy;
        pArr.push({x: ipx, y: ipy});
    }

    for (let i = 0; i < pArr.length - 1; i++) {
        let p1 = pArr[i];
        let p2 = pArr[i + 1];
        drawLine(ctx, p1.x, p1.y, p2.x, p2.y, color, 1);
    }
}

function rend(ele, funcList) {
    drawCoordinate(ele);
    for (let func of funcList) {
        drawFunc(ele, func, RANGE);
    }
}

window.onload = function () {

    let mainCan = document.querySelector(`.mainCanvas`);
    mainCan.width = `${LEN}`;
    mainCan.height = `${LEN}`;
    let funcInputEle = document.querySelector(`.funcInput`);

    // 网格显示开关
    let gridSwitch = document.querySelector(`.gridSwitch`);
    gridSwitch.addEventListener("click", () => {
        OPEN_GRID = !OPEN_GRID;
        if (OPEN_GRID) {
            gridSwitch.innerHTML = "关闭网格";
        } else {
            gridSwitch.innerHTML = "开启网格";
        }
        rend(mainCan, fArr);
    });

    // 刻度数字显示开关
    let numberSwitch = document.querySelector(`.numberSwitch`);
    numberSwitch.addEventListener("click", () => {
        OPEN_NUMBER = !OPEN_NUMBER;
        if (OPEN_NUMBER) {
            numberSwitch.innerHTML = "关闭刻度数字";
        } else {
            numberSwitch.innerHTML = "开启刻度数字";
        }
        rend(mainCan, fArr);
    });

    // 自定义设置范围
    let rageSetFree = document.querySelector(`.rageSetFree`);
    rageSetFree.onblur = function () {
        RANGE = +rageSetFree.value;
        rend(mainCan, fArr);
    }

    // 网格宽度设置
    let gridLen = document.querySelector(`.gridLen`);
    gridLen.onblur = function () {
        GRID_LEN = +gridLen.value;
        rend(mainCan, fArr);
    }

    // 初始化一下放上网格
    drawCoordinate(mainCan);

    let fArr = [
        x => Math.sin(x),
        x => x ** 2,
        x => x,
        x => Math.log(x)
    ];

    // 更新函数！
    let updateFuncBtn = document.querySelector(`.updateFunc`);
    updateFuncBtn.addEventListener("click", () => {
        let strList = replaceFuncStr(funcInputEle.value).split(";");
        console.log(strList);

        fArr = [];
        for (let str of strList) {
            if (str === "") {
                continue;
            }
            fArr.push(eval("x => " + str));
        }
        console.log(fArr);

        rend(mainCan, fArr);
    });
    // 一开始就先画以下
    rend(mainCan, fArr);

    // 观察范围大概拖动
    let rEle = document.querySelector(`.rangeSet`);
    rEle.addEventListener("input", () => {
        RANGE = +rEle.value;
        rageSetFree.value = RANGE;
        rend(mainCan, fArr);
    })
}

